package com.stiove.whwh.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.stiove.whwh.dao.mapper.UserMapper;
import com.stiove.whwh.dao.mapper.UserWxCodeMapper;
import com.stiove.whwh.dao.pojo.User;
import com.stiove.whwh.dao.pojo.UserWxCode;
import com.stiove.whwh.service.UserService;
import com.stiove.whwh.utils.JWTUtils;
import com.stiove.whwh.utils.OssUtils;
import com.stiove.whwh.utils.SampleUtils;
import com.stiove.whwh.utils.UserThreadLocal;
import com.stiove.whwh.vo.Env;
import com.stiove.whwh.vo.Result;
import com.stiove.whwh.vo.params.UserLoginParams;
import com.stiove.whwh.vo.params.WxInfoParams;
import com.stiove.whwh.vo.params.WxUserLoginParams;
import lombok.Data;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Data
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserWxCodeMapper userWxCodeMapper;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private Env env;

    @Value("${wx.secret}")
    private String secret;

    @Override
    @Transactional
    public Result userLogin(String phone, String smsCode) {
        User userInfo = userMapper.getUserByPhone(phone);

        if (userInfo == null){
            userInfo =this.userRegister(phone);
        }
        Long userId = userInfo.getId();

        String code = redisTemplate.opsForValue().get(phone);
        if (StringUtils.isBlank(code) || !code.equals(smsCode)){
            return new Result(Result.USER_ERROR,"验证码错误");
        }

        String token = JWTUtils.createToken(userId);

        redisTemplate.opsForValue().set(token, JSON.toJSONString(userInfo));
        return new Result(Result.SUCCESS,"成功",token);
    }

    private User getUserByPhone(String phone) {
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(User::getPhone,phone);
        wrapper.last("limit 1");
        User userInfo = userMapper.selectOne(wrapper);
        return userInfo;
    }

    private User userRegister(String phone) {
        User userInfo = new User();
        userInfo.setPhone(phone);
        userInfo.setUsername(phone);
        userInfo.setUpdateTime(System.currentTimeMillis());
        userMapper.insert(userInfo);
        return this.getUserByPhone(phone);
    }

    @Override
    public Result userRegister(UserLoginParams user) {
        User userInfo = new User();

        userInfo.setPhone(user.getPhone());
        userInfo.setPassword(user.getPassword());
        userInfo.setUsername(user.getUsername());
//        userInfo.setHeadImg(user.getHeadImg());
        userInfo.setUpdateTime(System.currentTimeMillis());

        int userId = userMapper.insert(userInfo);
        if (userId == 0){
            return new Result(Result.SERVER_ERROR,"服务器错误");
        }

        return new Result(Result.SUCCESS,"成功",user.getHeadImg());
    }

    @SneakyThrows
    @Override
    public Result send_message(String phone) {
        Random r = new Random();
        SampleUtils sampleUtils = new SampleUtils();

        String smsCode = redisTemplate.opsForValue().get(phone);
        if (!StringUtils.isBlank(smsCode)){
            return new Result(Result.USER_ERROR,"请稍后再试");
        }
        String code = "";
        for (int i=0;i<4;i++){
            code = code + r.nextInt(10);
        }
        redisTemplate.opsForValue().set(phone,code,3, TimeUnit.MINUTES);

        if(!sampleUtils.send_message(phone,code,env.ak,env.sk,env.signName,env.templateCode)){
            return new Result(Result.SERVER_ERROR,"服务器错误");
        }
        return new Result(Result.SUCCESS,"成功");
    }

    @Override
    @Transactional
    public Result updateHeadImg(MultipartFile img) throws IOException {
        Long userId = UserThreadLocal.get().getId();
        long time = System.currentTimeMillis();
        String objectName ="header/" + time + img.getOriginalFilename();

        User user = new User();
        user.setId(userId);
        user.setHeadImg(env.bucket + objectName);
        user.setUpdateTime(time);
        OssUtils ossUtils = new OssUtils();
        try {
            ossUtils.upload(img.getInputStream(), objectName,env);
            userMapper.updateById(user);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(Result.SERVER_ERROR,"失败");
        }

        return new Result(Result.SUCCESS,"成功");
    }

    @Override
    public Result updateUsername(String username) {
        User user = new User();
        user.setId(UserThreadLocal.get().getId());
        user.setUsername(username);
        try {
            userMapper.updateById(user);
        } catch (Exception e) {
            return new Result(Result.SERVER_ERROR,"失败",e.getMessage());
        }
        return new Result(Result.SUCCESS,"成功");
    }

    @Override
    public Result userInfo() {
        Long id = UserThreadLocal.get().getId();
        User userInfo = userMapper.getUserInfo(id);
        return new Result(Result.SUCCESS,"成功",userInfo);
    }

    @Override
    @Transactional
    public Result wxUserLogin(WxUserLoginParams user) {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));
        String uri = "https://api.weixin.qq.com/sns/jscode2session?appid=" + user.getAppId() + "&secret="+ secret +"&js_code=" + user.getCode() +"&grant_type=authorization_code";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
        HttpEntity<String> entity = new HttpEntity<String>(headers);
        ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);

        WxInfoParams parse = JSONObject.parseObject(response.getBody(),WxInfoParams.class);
        if (parse.getErrcode() != 0){
            return new Result(Result.USER_ERROR,"ErrCode :" + parse.getErrcode() +"；"+parse.getErrmsg());
        }

        parse.setWxCode(parse.getOpenid());
        UserWxCode wxCode = userWxCodeMapper.getWxCodeByCode(parse.getWxCode());


        if (wxCode == null){
            try {
                User userInfo = new User();
                userInfo.setPhone(user.getPhone());
                userInfo.setUsername(user.getUsername());
                userInfo.setHeadImg(user.getHeadImg());
                userInfo.setUpdateTime(System.currentTimeMillis());
                userMapper.insert(userInfo);

                UserWxCode userWxCode = new UserWxCode();
                userWxCode.setWxCode(parse.getWxCode());
                userWxCode.setUserId(userInfo.getId());
                userWxCodeMapper.insert(userWxCode);

                String token = JWTUtils.createToken(userWxCode.getUserId());
                User mapperUserInfo = userMapper.getUserInfo(userWxCode.getUserId());
                redisTemplate.opsForValue().set(token, JSON.toJSONString(mapperUserInfo));
                return new Result(Result.SUCCESS,"成功",token);
            }catch (Exception e){
                return new Result(Result.SERVER_ERROR,"服务器错误",e.getMessage());
            }
        }else{
            try {
                String token = JWTUtils.createToken(wxCode.getUserId());
                User mapperUserInfo = userMapper.getUserInfo(wxCode.getUserId());
                redisTemplate.opsForValue().set(token, JSON.toJSONString(mapperUserInfo));
                return new Result(Result.SUCCESS,"成功",token);
            }catch (Exception e){
                return new Result(Result.SERVER_ERROR,"服务器错误",e.getMessage());
            }

        }
    }



    public String checkToken(String token) {
        if (StringUtils.isBlank(token)){
            return  null;
        }

        Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
        if (stringObjectMap == null){
            return null;
        }

        String userInfo = redisTemplate.opsForValue().get(token);
        if (StringUtils.isBlank(userInfo)){
            return null;
        }
        return userInfo;

    }




}
